/**
 * 
 */
package com.ruyipu.forum.base;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;

/**
 * @author donald
 * 
 *         Cookies 执行算法
 *         <ol>
 *         <li>先取得系统保存的cookies</li>
 *         <li>如果不为空，把cookies交给cookieStore,并将cookieStore传给localContext，
 *         最后将localContext传给client， 以达到访问网站使用cookie的目的。</li>
 *         <li>如果为空，直接使用client访问网址</li>
 *         <li>访问完成后，取得cookiesStore中的cookies。如果原cookies中没有，则增加相应的cookies,若有，则更新。
 *         </li>
 *         </ol>
 */
public class TextService {

	public static final String TAG = TextService.class.getSimpleName();
	public static final int HTTP_GET = 1;
	public static final int HTTP_POST = 2;

	private static CookieStore cookieStore = new BasicCookieStore();
	private static HttpContext localContext = new BasicHttpContext();
	private static LocalCookie CookieManager = null;
	private static List<Cookie> myCookies = null;

	private TextService() {
	}

	private static void prepareCookies(Context context) {
		if (null == cookieStore) {
			cookieStore = new BasicCookieStore();
		}
		if (null == localContext) {
			localContext = new BasicHttpContext();
		}
		if (null == CookieManager) {
			CookieManager = LocalCookie.getInstance(context);
		}

		myCookies = CookieManager.getCookies();

		if (myCookies != null && !myCookies.isEmpty()) {
			for (int i = 0; i < myCookies.size(); i++) {
				cookieStore.addCookie(myCookies.get(i));
			}
			localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
		}
		localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
	}

	/**
	 * @throws IOException
	 * @throws JSONException
	 * @throws JSONExceptimsgon
	 */
	public static JSONObject execute(Context context, String url,
			List<NameValuePair> params) throws UnsupportedEncodingException,
			ClientProtocolException, IOException, JSONException {
		String result = execute(url, params, context);
		JSONObject object = null;
		if (null != result) {
			try {
				object = new JSONObject(result);
			} catch (JSONException e) {
				throw e;
			} finally {
				CookieManager.closeDatabase();
			}
		}
		// 如果是GET数据，则默认保存下来
		if (null != object && (null == params || params.isEmpty())) {
			String fileName = FileWriter.fixJSONFileName(url);
			FileWriter.write(fileName, result);
		}
		return object;
	}

	public static String execute(String url, List<NameValuePair> params,
			Context context) throws UnsupportedEncodingException,
			ClientProtocolException, IOException {
		
		if (null == url || "".equals(url)) {
			MyLog.e(TAG, "Empty url");
			return null;
		}
		MyLog.d(TAG, url);
		
		DefaultHttpClient client = new DefaultHttpClient();
	
		HttpParams httpParam = client.getParams();
		HttpConnectionParams.setConnectionTimeout(httpParam, Constants.HTTP_CONNECTION_TIMEOUT);
		HttpConnectionParams.setSoTimeout(httpParam, Constants.HTTP_SO_TIMEOUT);
		
		HttpResponse response;
		
		HttpPost request = new HttpPost(url);
		
		if (params != null) {
			MyLog.d(TAG, params.toString());
			HttpEntity entity;
			try {
				entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
				request.setEntity(entity);
			} catch (UnsupportedEncodingException e) {
				throw e;
			}
		}

		prepareCookies(context);

		long lStart = System.currentTimeMillis();
		try {
			response = client.execute(request, localContext);
		} catch (ClientProtocolException e) {
			throw e;
		} catch (IOException e) {
			throw e;
		} finally {
			CookieManager.closeDatabase();
		}
		long lEnd = System.currentTimeMillis();
		MyLog.d(TAG, "Get data from web takes " + (lEnd - lStart)
				+ " milliSecond");

		addOrUpdateCookies(cookieStore.getCookies());
		int statusCode = response.getStatusLine().getStatusCode();
		String result = null;
		if (statusCode == HttpStatus.SC_OK) {
			result = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
			MyLog.d(TAG, result);
		} else {
			MyLog.e(TAG, String.valueOf(statusCode));
		}

		return result;
	}

	private static void addOrUpdateCookies(List<Cookie> cookies) {
		if (cookies.isEmpty()) {
			MyLog.d(TAG, "No Cookie");
		} else {
			if (myCookies == null || myCookies.isEmpty()) {
				CookieManager.addCookies(cookies);
			} else {

				int cookiesSize = cookies.size();
				int myCookiesSize = myCookies.size();

				for (int i = 0; i < cookiesSize; i++) {
					boolean cookieExist = false;
					Cookie cookieAfter = cookies.get(i);
					for (int j = 0; j < myCookiesSize; j++) {
						Cookie cookieBefore = myCookies.get(j);
						if (cookieAfter.equals(cookieBefore)) {
							cookieExist = true;
							break;
						} else if (cookieAfter.getName().equals(
								cookieBefore.getName())) {
							CookieManager.updateCookie(cookies.get(i));
							cookieExist = true;
							break;
						}
					}
					if (!cookieExist) {
						CookieManager.addCookie(cookies.get(i));
					}
					MyLog.d("CookieAfterGet", cookies.get(i).toString());
					MyLog.d("CookieBeforGet", myCookies.get(i).toString());
				}
			}
		}
		CookieManager.closeDatabase();
	}

}
